#include "spectrum.h"
#include "private/spectrumprivatedefine.h"
#include "common/dataspecificationutils.h"
#include "common/binaryprocesshelper.h"
#include "common/xmldocument.h"
#include "private/spectrumdatafilecommondefine.h"
#include <QDebug>

namespace DataSpecificationGW
{
    Spectrum::Spectrum()
        : m_pSpectrumPrivate(new SpectrumPrivate)
    {
    }

    Spectrum::~Spectrum()
    {
    }

    /************************************************
     * 函数名   : setDataSpecificationVersion
     * 输入参数 :
       const DataSpecificationVersion eDataSpecificationVersion: 数据规范版本号
     * 输出参数 : NULL
     * 返回值   : void
     * 功能     : 设置数据规范版本号
     ************************************************/
    void Spectrum::setDataSpecificationVersion(const DataSpecificationVersion eDataSpecificationVersion)
    {
        m_pSpectrumPrivate->m_eDataSpecificationVersion = eDataSpecificationVersion;
    }

    /************************************************
     * 函数名   : setSpectrumHead
     * 输入参数 :
       const SpectrumHead& stSpectrumHead: 图谱头
     * 输出参数 : NULL
     * 返回值   : void
     * 功能     : 设置图谱头
     ************************************************/
    void Spectrum::setSpectrumHead(const SpectrumHead& stSpectrumHead)
    {
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumTypeCode = stSpectrumHead.eSpectrumTypeCode;
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrSpectrumGenerationTime = stSpectrumHead.qstrSpectrumGenerationTime;
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumCharacter = stSpectrumHead.eSpectrumCharacter;
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentName = stSpectrumHead.qstrEquipmentName;
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentCode = stSpectrumHead.qstrEquipmentCode;
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointName = stSpectrumHead.qstrTestPointName;
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointCode = stSpectrumHead.qstrTestPointCode;
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.sDetectionChannelID = stSpectrumHead.sDetectionChannelID;
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType = stSpectrumHead.eStorageDataType;
    }

    /************************************************
     * 函数名   : setSpectrumTypeCode
     * 输入参数 :
       const SpectrumCode eSpectrumCode: 图谱类型编码
     * 输出参数 : NULL
     * 返回值   : void
     * 功能     : 设置图谱类型编码
     ************************************************/
    void Spectrum::setSpectrumTypeCode(const SpectrumTypeCode eSpectrumCode)
    {
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumTypeCode = eSpectrumCode;
    }

    /************************************************
     * 函数名   : setSpectrumTypeCode
     * 输入参数 :
       const QString& qstrSpectrumGenerationTime: 图谱生成时间
     * 输出参数 : NULL
     * 返回值   : void
     * 功能     : 设置图谱生成时间
     ************************************************/
    void Spectrum::setSpectrumGenerationTime(const QString& qstrSpectrumGenerationTime)
    {
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrSpectrumGenerationTime = qstrSpectrumGenerationTime;
    }

    /************************************************
     * 函数名   : setSpectrumCharacter
     * 输入参数 :
       const MapProperty eSpectrumCharacter: 图谱性质
     * 输出参数 : NULL
     * 返回值   : void
     * 功能     : 设置图谱性质
     ************************************************/
    void Spectrum::setSpectrumCharacter(const SpectrumCharacter eSpectrumCharacter)
    {
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumCharacter = eSpectrumCharacter;
    }

    /************************************************
     * 函数名   : setEquipmentName
     * 输入参数 :
       const QString& qstrEquipmentName: 设备名称
     * 输出参数 : NULL
     * 返回值   : void
     * 功能     : 设置设备名称
     ************************************************/
    void Spectrum::setEquipmentName(const QString& qstrEquipmentName)
    {
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentName = qstrEquipmentName;
    }

    /************************************************
     * 函数名   : setEquipmentCode
     * 输入参数 :
       const QString& qstrEquipmentCode: 设备编码
     * 输出参数 : NULL
     * 返回值   : void
     * 功能     : 设置设备编码
     ************************************************/
    void Spectrum::setEquipmentCode(const QString& qstrEquipmentCode)
    {
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentCode = qstrEquipmentCode;
    }

    /************************************************
     * 函数名   : setTestPointName
     * 输入参数 :
       const QString& qstrTestPointName: 测点名称
     * 输出参数 : NULL
     * 返回值   : void
     * 功能     : 设置测点名称
     ************************************************/
    void Spectrum::setTestPointName(const QString& qstrTestPointName)
    {
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointName = qstrTestPointName;
    }

    /************************************************
     * 函数名   : setTestPointCode
     * 输入参数 :
       const QString& qstrTestPointCode: 测点编码
     * 输出参数 : NULL
     * 返回值   : void
     * 功能     : 设置测点编码
     ************************************************/
    void Spectrum::setTestPointCode(const QString& qstrTestPointCode)
    {
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointCode = qstrTestPointCode;
    }

    /************************************************
     * 函数名   : setDetectionChannelIdentification
     * 输入参数 :
       const qint16 sDetectionChannelIdentification: 检测通道标识
     * 输出参数 : NULL
     * 返回值   : void
     * 功能     : 设置检测通道标识
     ************************************************/
    void Spectrum::setDetectionChannelIdentification(const qint16 sDetectionChannelIdentification)
    {
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.sDetectionChannelID = sDetectionChannelIdentification;
    }

    /************************************************
     * 函数名   : setStorageDataType
     * 输入参数 :
       const StorageDataType eStorageDataType: 存储数据类型
     * 输出参数 : NULL
     * 返回值   : void
     * 功能     : 设置存储数据类型
     ************************************************/
    void Spectrum::setStorageDataType(const StorageDataType eStorageDataType)
    {
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType = eStorageDataType;
    }

    /************************************************
     * 函数名   : getSpectrumHead
     * 输入参数 : NULL
     * 输出参数 :
       SpectrumHead& stSpectrumHead: 图谱头结构体
     * 返回值   : void
     * 功能     : 获取图谱头
     ************************************************/
    void Spectrum::getSpectrumHead(SpectrumHead& stSpectrumHead)
    {
        stSpectrumHead.eSpectrumTypeCode = static_cast<SpectrumTypeCode>(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumTypeCode);
        stSpectrumHead.iSpectrumDataLength = m_pSpectrumPrivate->m_stSpectrumHeadPrivate.iSpectrumDataLength;
        stSpectrumHead.qstrSpectrumGenerationTime = m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrSpectrumGenerationTime;
        stSpectrumHead.eSpectrumCharacter = static_cast<SpectrumCharacter>(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumCharacter);
        stSpectrumHead.qstrEquipmentName = m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentName;
        stSpectrumHead.qstrEquipmentCode = m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentCode;
        stSpectrumHead.qstrTestPointName = m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointName;
        stSpectrumHead.qstrTestPointCode = m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointCode;
        stSpectrumHead.sDetectionChannelID = m_pSpectrumPrivate->m_stSpectrumHeadPrivate.sDetectionChannelID;
        stSpectrumHead.eStorageDataType = static_cast<StorageDataType>(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType);
    }

    /************************************************
     * 函数名   : saveAsBinary
     * 输入参数 :
       QByteArray& qbaPackage: 数据
     * 输出参数 : NULL
     * 返回值   : bool
     * 功能     : 保存成二进制数据
     ************************************************/
    bool Spectrum::saveAsBinary(QByteArray& qbaPackage)
    {
        QDataStream out(&qbaPackage, QIODevice::ReadWrite);
        out.setByteOrder(QDataStream::LittleEndian);
        out.setFloatingPointPrecision(QDataStream::SinglePrecision);

        saveBinarySpectrumHead(out);     // 保存文件头
        saveBinarySpectrumExtInfo(out);   // 保存数据第一段
        saveBinarySpectrumData(out);  // 保存数据第二段
        updateBinaryDataLength(out);    // 更新图谱数据长度

        return true;
    }

    /************************************************
     * 函数名   : saveAsXML
     * 输入参数 :
       XMLDocument& xmlDocumentObj: xml文档对象
     * 输出参数 : NULL
     * 返回值   : bool
     * 功能     : 保存成XML数据
     ************************************************/
    bool Spectrum::saveAsXML(XMLDocument& xmlDocumentObj)
    {
        QDomElement root = xmlDocumentObj.documentElement();
        xmlDocumentObj.beginElement(root);
        xmlDocumentObj.beginElement(STR_FILE_NODE_NAME_SPECTRUMS);
        QDomElement element = xmlDocumentObj.addElement(STR_FILE_NODE_NAME_SPECTRUM);
        xmlDocumentObj.beginElement(element);
        element = xmlDocumentObj.addElement(spectrumName());

        saveXMLSpectrumHead(xmlDocumentObj, element);
        saveXMLSpectrumExtInfo(xmlDocumentObj, element);
        saveXMLSpectrumData(xmlDocumentObj, element);
        xmlDocumentObj.endElement();

        return true;
    }

    /************************************************
     * 函数名   : saveAsJSON
     * 输入参数 :
       rapidjson::Document::AllocatorType& alloc:
       rapidjson::Value& jsonValue: json数据
     * 输出参数 : NULL
     * 返回值   : bool
     * 功能     : 保存成JSON数据
     ************************************************/
    bool Spectrum::saveAsJSON(rapidjson::Document::AllocatorType& alloc, rapidjson::Value& jsonValue)
    {
        jsonValue.SetObject();

        rapidjson::Value jsonSpectrumHeadValue;
        jsonSpectrumHeadValue.SetObject();
        if (!saveJSONSpectrumHead(alloc, jsonSpectrumHeadValue))
        {
            return false;
        }     
        jsonValue.AddMember(rapidjson::Value(STR_SPECTRUM_NODE_HEAD, alloc), jsonSpectrumHeadValue.Move(), alloc);

        rapidjson::Value jsonSpectrumExtInfoValue;
        jsonSpectrumExtInfoValue.SetObject();
        if (!saveJSONSpectrumExtInfo(alloc, jsonSpectrumExtInfoValue))
        {
            return false;
        }
        jsonValue.AddMember(rapidjson::Value(STR_SPECTRUM_NODE_EXTINFORMATION, alloc), jsonSpectrumExtInfoValue.Move(), alloc);

        rapidjson::Value jsonSpectrumDataValue;
        jsonSpectrumDataValue.SetObject();
        if (!saveJSONSpectrumData(alloc, jsonSpectrumDataValue))
        {
            return false;
        }

        jsonValue.AddMember(rapidjson::Value(STR_SPECTRUM_NODE_DATA, alloc), jsonSpectrumDataValue.Move(), alloc);

        return true;
    }

    /************************************************
     * 函数名   : parseBinaryData
     * 输入参数 :
       const QByteArray& qbaData: 二进制数据
     * 输出参数 : NULL
     * 返回值   : bool
     * 功能     : 解析二进制数据
     ************************************************/
    bool Spectrum::parseBinaryData(const QByteArray& qbaData)
    {
        QDataStream in(qbaData);
        in.setByteOrder(QDataStream::LittleEndian);
        in.setFloatingPointPrecision(QDataStream::SinglePrecision);

        // 解析map头（map公共部分）
        if (!parseBinarySpectrumHead(in))
        {
            return false;
        }

        //解析map数据
        return parseBinarySpectrumExtInfo(in) & parseBinarySpectrumData(in);
    }

    /************************************************
     * 函数名   : parseXMLData
     * 输入参数 :
       XMLDocument& xmlDocumentObj: xml文档对象
     * 输出参数 : NULL
     * 返回值   : bool
     * 功能     : 解析XML数据
     ************************************************/
    bool Spectrum::parseXMLData(XMLDocument& xmlDocumentObj)
    {
        parseXMLSpectrumHead(xmlDocumentObj);
        parseXMLSpectrumExtInfo(xmlDocumentObj);
        parseXMLSpectrumData(xmlDocumentObj);

        return true;
    }

    /************************************************
     * 函数名   : parseJSONData
     * 输入参数 :
       const rapidjson::Value& jsonValue: json数据
     * 输出参数 : NULL
     * 返回值   : bool
     * 功能     : 解析JSON数据
     ************************************************/
    bool Spectrum::parseJSONData(const rapidjson::Value& jsonValue)
    {
        if (!jsonValue.IsObject())
        {
            return false;
        }

        if (jsonValue.HasMember(STR_SPECTRUM_NODE_HEAD))
        {
            const rapidjson::Value& jsonSpectrumHeadValue = jsonValue[STR_SPECTRUM_NODE_HEAD];
            parseJSONSpectrumHead(jsonSpectrumHeadValue);
        }

        if (jsonValue.HasMember(STR_SPECTRUM_NODE_EXTINFORMATION))
        {
            const rapidjson::Value& jsonSpectrumExtInfoValue = jsonValue[STR_SPECTRUM_NODE_EXTINFORMATION];
            parseJSONSpectrumExtInfo(jsonSpectrumExtInfoValue);
        }

        if (jsonValue.HasMember(STR_SPECTRUM_NODE_DATA))
        {
            const rapidjson::Value& jsonSpectrumDataValue = jsonValue[STR_SPECTRUM_NODE_DATA];
            parseJSONSpectrumData(jsonSpectrumDataValue);
        }

        return true;
    }

    /************************************************
     * 函数名   : storageDataType
     * 输入参数 : NULL
     * 输出参数 : NULL
     * 返回值   : StorageDataType
     * 功能     : 图谱的数据类型
     ************************************************/
    StorageDataType Spectrum::storageDataType()
    {
        return static_cast<StorageDataType>(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType);
    }

    /************************************************
     * 函数名   : spectrumTypeCode
     * 输入参数 : NULL
     * 输出参数 : NULL
     * 返回值   : SpectrumTypeCode
     * 功能     : 图谱类型编码
     ************************************************/
    SpectrumTypeCode Spectrum::spectrumTypeCode()
    {
        return static_cast<SpectrumTypeCode>(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumTypeCode);
    }

    /************************************************
     * 函数名   : saveBinarySpectrumHead
     * 输入参数 :
       QDataStream& out: 输出流
     * 输出参数 : NULL
     * 返回值   : bool
     * 功能     : 保存二进制头部
     ************************************************/
    bool Spectrum::saveBinarySpectrumHead(QDataStream& out)
    {
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipeSpectrumTypeCode) out << m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumTypeCode;        // 图谱类型编码
        qDebug() << "Spectrum::saveBinarySpectrumHead SpectrumCode: " << m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumTypeCode;
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipSpectrumDataLength) out << (qint32)(0);// map data length
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipSpectrumGenerationTime) DataSpecificationUtils::convertStringToBinary(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrSpectrumGenerationTime, TYPE_DATETIME, out, DATETIME_STR_LENGTH);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipSpectrumCharacter) out << m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumCharacter;
        if (V_1_1_0_0 == m_pSpectrumPrivate->m_eDataSpecificationVersion
                || V_4_1_0_2 == m_pSpectrumPrivate->m_eDataSpecificationVersion)
        {
            if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipEquipmentName) DataSpecificationUtils::convertStringToBinary(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentName, TYPE_UNICODE, out, EQUIPMENT_NAME_LENGTH_OLD);
            if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipEquipmentCode) DataSpecificationUtils::convertStringToBinary(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentCode, TYPE_ASCII, out, EQUIPMENT_CODE_LENGTH_OLD);
        }
        else
        {
            if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipEquipmentName) DataSpecificationUtils::convertStringToBinary(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentName, TYPE_UNICODE, out, EQUIPMENT_NAME_LENGTH);
            if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipEquipmentCode) DataSpecificationUtils::convertStringToBinary(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentCode, TYPE_ASCII, out, EQUIPMENT_CODE_LENGTH);
        }
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipTestPointName) DataSpecificationUtils::convertStringToBinary(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointName, TYPE_UNICODE, out, UNICODE_STR_LENGTH);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipTestPointCode) DataSpecificationUtils::convertStringToBinary(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointCode, TYPE_ASCII, out, 32);

        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipDetectionChannelID) out << m_pSpectrumPrivate->m_stSpectrumHeadPrivate.sDetectionChannelID;
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipStorageDataType) out << m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType;   //存储数据类型

        return true;
    }

    /************************************************
     * 函数名   : saveXMLSpectrumHead
     * 输入参数 :
       XMLDocument& xmlDocumentObj: xml文档对象
       QDomElement& element: dom元素
     * 输出参数 : NULL
     * 返回值   : bool
     * 功能     : 保存XML头部
     ************************************************/
    bool Spectrum::saveXMLSpectrumHead(XMLDocument& xmlDocumentObj, QDomElement& element)
    {
        qDebug() << "Spectrum::saveXMLSpectrumHead m_pSpectrumPrivate->m_stSpectrumHeadPrivate.eCode:" << m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumTypeCode;
        xmlDocumentObj.beginElement(element);
        xmlDocumentObj.beginElement(STR_SPECTRUM_NODE_HEAD);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipeSpectrumTypeCode) xmlDocumentObj.setValue(TEXT_SPECTRUM_CODE, QString::number(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumTypeCode));
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipSpectrumDataLength) xmlDocumentObj.setValue(TEXT_SPECTRUM_DATA_LENGTH, QString::number(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.iSpectrumDataLength));
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipSpectrumGenerationTime) xmlDocumentObj.setValue(TEXT_SPECTRUM_CREATE_TIME, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrSpectrumGenerationTime);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipSpectrumCharacter) xmlDocumentObj.setValue(TEXT_SPECTRUM_PROPERTY, QString::number(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumCharacter));
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipEquipmentName) xmlDocumentObj.setValue(TEXT_EQUIPMENT_NAME, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentName);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipEquipmentCode) xmlDocumentObj.setValue(TEXT_EQUIPMENT_CODE, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentCode);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipTestPointName) xmlDocumentObj.setValue(TEXT_TEST_POINT_NAME, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointName);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipTestPointCode) xmlDocumentObj.setValue(TEXT_TEST_POINT_CODE, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointCode);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipDetectionChannelID) xmlDocumentObj.setValue(TEXT_CHANNEL_INDEX, QString::number(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.sDetectionChannelID));
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipStorageDataType) xmlDocumentObj.setValue(TEXT_DATA_PRIMITIVE_TYPE, QString::number(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType));

        return true ;
    }

    /************************************************
     * 函数名   : saveJSONSpectrumHead
     * 输入参数 :
       rapidjson::Document::AllocatorType& alloc:
       rapidjson::Value& jsonValue: json数据
     * 输出参数 : NULL
     * 返回值   : bool
     * 功能     : 保存JSON头部
     ************************************************/
    bool Spectrum::saveJSONSpectrumHead(rapidjson::Document::AllocatorType& alloc, rapidjson::Value& jsonValue)
    {
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipeSpectrumTypeCode) saveJSONField(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumTypeCode, TEXT_SPECTRUM_CODE, alloc, jsonValue);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipSpectrumDataLength) saveJSONField(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.iSpectrumDataLength, TEXT_SPECTRUM_DATA_LENGTH, alloc, jsonValue);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipSpectrumGenerationTime) saveJSONField(QString::number(DataSpecificationUtils::serializeDateTime(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrSpectrumGenerationTime)), TEXT_SPECTRUM_CREATE_TIME, alloc, jsonValue);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipSpectrumCharacter) saveJSONField(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumCharacter, TEXT_SPECTRUM_PROPERTY, alloc, jsonValue);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipEquipmentName) saveJSONField(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentName, TEXT_EQUIPMENT_NAME, alloc, jsonValue);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipEquipmentCode) saveJSONField(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentCode, TEXT_EQUIPMENT_CODE, alloc, jsonValue);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipTestPointName) saveJSONField(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointName, TEXT_TEST_POINT_NAME, alloc, jsonValue);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipTestPointCode) saveJSONField(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointCode, TEXT_TEST_POINT_CODE, alloc, jsonValue);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipDetectionChannelID) saveJSONField(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.sDetectionChannelID, TEXT_CHANNEL_INDEX, alloc, jsonValue);
        if (!m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipStorageDataType) saveJSONField(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType, TEXT_DATA_PRIMITIVE_TYPE, alloc, jsonValue);

        return true;
    }

    /************************************************
     * 函数名   : parseBinarySpectrumHead
     * 输入参数 :
       QDataStream& in: 输入流
     * 输出参数 : NULL
     * 返回值   : bool
     * 功能     : 解析二进制头部
     ************************************************/
    bool Spectrum::parseBinarySpectrumHead(QDataStream& in)
    {
        if (!in.device()->seek(0))
        {
            qDebug() << "Spectrum::parseBinarySpectrumData failed";
            return false;
        }

        parseBinaryField(in, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipeSpectrumTypeCode, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumTypeCode, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHaseSpectrumTypeCode);
        parseBinaryField(in, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipSpectrumDataLength, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.iSpectrumDataLength, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasSpectrumDataLength);
        parseBinaryField(in, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipSpectrumGenerationTime, DataSpecificationGW::TYPE_DATETIME, DATETIME_STR_LENGTH, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrSpectrumGenerationTime, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasSpectrumGenerationTime);
        parseBinaryField(in, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipSpectrumCharacter, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumCharacter, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasSpectrumCharacter);
        if (V_1_1_0_0 == m_pSpectrumPrivate->m_eDataSpecificationVersion
                || V_4_1_0_2 == m_pSpectrumPrivate->m_eDataSpecificationVersion)
        {
            // 旧版本和新版本长度不一样
            parseBinaryField(in, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipEquipmentName, DataSpecificationGW::TYPE_UNICODE, EQUIPMENT_NAME_LENGTH_OLD, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentName, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasEquipmentName);
            parseBinaryField(in, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipEquipmentCode, DataSpecificationGW::TYPE_ASCII, EQUIPMENT_CODE_LENGTH_OLD, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentCode, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasEquipmentCode);
        }
        else
        {
            parseBinaryField(in, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipEquipmentName, DataSpecificationGW::TYPE_UNICODE, EQUIPMENT_NAME_LENGTH, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentName, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasEquipmentName);
            parseBinaryField(in, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipEquipmentCode, DataSpecificationGW::TYPE_ASCII, EQUIPMENT_CODE_LENGTH, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentCode, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasEquipmentCode);
        }
        parseBinaryField(in, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipTestPointName, DataSpecificationGW::TYPE_UNICODE, UNICODE_STR_LENGTH, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointName, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasTestPointName);
        parseBinaryField(in, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipTestPointCode, DataSpecificationGW::TYPE_ASCII, 32, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointCode, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasTestPointCode);
        parseBinaryField(in, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipDetectionChannelID, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.sDetectionChannelID, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasDetectionChannelID);
        parseBinaryField(in, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bSkipStorageDataType, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasStorageDataType);

        qDebug() << "Spectrum::parseBinarySpectrumHead SpectrumCode: " << m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumTypeCode;
        return in.status() == QDataStream::Ok;
    }

    /************************************************
     * 函数名   : parseXMLSpectrumHead
     * 输入参数 :
       XMLDocument& xmlDocumentObj: xml文档对象
     * 输出参数 : NULL
     * 返回值   : bool
     * 功能     : 解析XML头部
     ************************************************/
    bool Spectrum::parseXMLSpectrumHead(XMLDocument& xmlDocumentObj)
    {
        bool bRet = true;

        xmlDocumentObj.beginElement(spectrumName());
        xmlDocumentObj.beginElement(STR_SPECTRUM_NODE_HEAD);

        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumTypeCode = xmlDocumentObj.value(TEXT_SPECTRUM_CODE).toUInt();
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.iSpectrumDataLength = xmlDocumentObj.value(TEXT_SPECTRUM_DATA_LENGTH).toInt();
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrSpectrumGenerationTime = xmlDocumentObj.value(TEXT_SPECTRUM_CREATE_TIME);
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumCharacter = xmlDocumentObj.value(TEXT_SPECTRUM_PROPERTY).toUInt();
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentName = xmlDocumentObj.value(TEXT_EQUIPMENT_NAME);
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentCode = xmlDocumentObj.value(TEXT_EQUIPMENT_CODE);
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointName = xmlDocumentObj.value(TEXT_TEST_POINT_NAME);
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointCode = xmlDocumentObj.value(TEXT_TEST_POINT_CODE);
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.sDetectionChannelID = xmlDocumentObj.value(TEXT_CHANNEL_INDEX).toInt();
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType = xmlDocumentObj.value(TEXT_DATA_PRIMITIVE_TYPE).toUInt();

        xmlDocumentObj.endElement();
        xmlDocumentObj.endElement();

        return bRet;
    }

    /************************************************
     * 函数名   : parseJSONSpectrumHead
     * 输入参数 :
       const rapidjson::Value& jsonValue: json数据
     * 输出参数 : NULL
     * 返回值   : bool
     * 功能     : 解析JSON头部
     ************************************************/
    bool Spectrum::parseJSONSpectrumHead(const rapidjson::Value& jsonValue)
    {
        parseJSONField(jsonValue, TEXT_SPECTRUM_CODE, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumTypeCode, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHaseSpectrumTypeCode);
        parseJSONField(jsonValue, TEXT_SPECTRUM_DATA_LENGTH, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.iSpectrumDataLength, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasSpectrumDataLength);
        parseJSONField(jsonValue, TEXT_SPECTRUM_CREATE_TIME, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrSpectrumGenerationTime, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasSpectrumGenerationTime);
        parseJSONField(jsonValue, TEXT_SPECTRUM_PROPERTY, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucSpectrumCharacter, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasSpectrumCharacter);
        parseJSONField(jsonValue, TEXT_EQUIPMENT_NAME, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentName, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasEquipmentName);
        parseJSONField(jsonValue, TEXT_EQUIPMENT_CODE, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrEquipmentCode, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasEquipmentCode);
        parseJSONField(jsonValue, TEXT_TEST_POINT_NAME, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointName, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasTestPointName);
        parseJSONField(jsonValue, TEXT_TEST_POINT_CODE, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.qstrTestPointCode, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasTestPointCode);
        parseJSONField(jsonValue, TEXT_CHANNEL_INDEX, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.sDetectionChannelID, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasDetectionChannelID);
        parseJSONField(jsonValue, TEXT_DATA_PRIMITIVE_TYPE, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType, m_pSpectrumPrivate->m_stSpectrumHeadPrivate.bHasStorageDataType);

        return true;
    }

    /************************************************
     * 函数名   : updateBinaryFileLength
     * 输入参数 :
       QDataStream& out: 输出流
     * 输出参数 : NULL
     * 返回值   : void
     * 功能     : 更新二进制数据长度
     ************************************************/
    void Spectrum::updateBinaryDataLength(QDataStream& out)
    {
        m_pSpectrumPrivate->m_stSpectrumHeadPrivate.iSpectrumDataLength = out.device()->size();

        qDebug() << "Spectrum::updateBinaryDataLength:" << m_pSpectrumPrivate->m_stSpectrumHeadPrivate.iSpectrumDataLength;
        out.device()->seek(1);
        out << m_pSpectrumPrivate->m_stSpectrumHeadPrivate.iSpectrumDataLength;
    }

    /************************************************
     * 函数名   : perDataSize
     * 输入参数 : NULL
     * 输出参数 : NULL
     * 返回值   : int
     * 功能     : 获取当前存储数据类型每个占用的字节数
     ************************************************/
    int Spectrum::perDataSize()
    {
        int perDataSize = 0;
        if(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType == DATA_TYPE_FLOAT)
        {
            perDataSize = sizeof(float)/sizeof(char);
        }
        else if(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType == DATA_TYPE_DOUBLE)
        {
            perDataSize = sizeof(double)/sizeof(char);
        }
        else if(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType == DATA_TYPE_INT8)
        {
            perDataSize = sizeof(qint8)/sizeof(char);
        }
        else if(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType == DATA_TYPE_UINT8)
        {
            perDataSize = sizeof(quint8)/sizeof(char);
        }
        else if(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType == DATA_TYPE_INT16)
        {
            perDataSize = sizeof(qint16)/sizeof(char);
        }
        else if(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType == DATA_TYPE_INT32)
        {
            perDataSize = sizeof(qint32)/sizeof(char);
        }
        else if(m_pSpectrumPrivate->m_stSpectrumHeadPrivate.ucStorageDataType == DATA_TYPE_INT64)
        {
            perDataSize = sizeof(qint64)/sizeof(char);
        }

        return perDataSize;
    }

}
